URLSession 教程

概述

在现代应用程序开发中,与服务器进行数据交互是非常常见的任务。iOS 提供了 URLSession 类来处理网络请求。URLSession 是一个强大的 API,允许你发送和接收数据,下载和上传文件,以及处理各种网络任务。

本教程将带你深入了解 URLSession 的使用,包括如何发送 GET 和 POST 请求,处理响应数据,以及处理错误。

1. URLSession 基础

1.1 什么是 URLSession?

URLSession 是 Foundation 框架中的一个类,用于处理与 URL 相关的网络请求。它提供了多种方法来执行网络操作,包括:

  • 数据任务 (Data Task): 用于从服务器获取数据。
  • 上传任务 (Upload Task): 用于将数据上传到服务器。
  • 下载任务 (Download Task): 用于从服务器下载文件。

1.2 URLSession 的组成

URLSession 由以下几个部分组成:

  • URLSession: 管理网络请求的会话。
  • URLSessionConfiguration: 配置会话的属性,如超时时间、缓存策略等。
  • URLSessionTask: 实际执行网络请求的任务,如数据任务、上传任务和下载任务。

2. 发送 GET 请求

2.1 创建 URLSession

首先,我们需要创建一个 URLSession 实例。默认情况下,URLSession 使用共享的会话配置,但你也可以自定义配置。

let session = URLSession.shared

2.2 创建 URL 和 URLRequest

接下来,我们需要创建一个 URL 对象和一个 URLRequest 对象。URLRequest 包含了请求的 URL、请求方法、请求头等信息。

guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
    fatalError("Invalid URL")
}

var request = URLRequest(url: url)
request.httpMethod = "GET"

2.3 创建并启动数据任务

现在,我们可以创建一个数据任务并启动它。数据任务会异步执行,并在完成后调用回调函数。

let task = session.dataTask(with: request) { data, response, error in
    if let error = error {
        print("Error: \(error.localizedDescription)")
        return
    }
    
    guard let data = data else {
        print("No data received")
        return
    }
    
    if let responseString = String(data: data, encoding: .utf8) {
        print("Response: \(responseString)")
    }
}

task.resume()

2.4 完整代码示例

import Foundation

let session = URLSession.shared

guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
    fatalError("Invalid URL")
}

var request = URLRequest(url: url)
request.httpMethod = "GET"

let task = session.dataTask(with: request) { data, response, error in
    if let error = error {
        print("Error: \(error.localizedDescription)")
        return
    }
    
    guard let data = data else {
        print("No data received")
        return
    }
    
    if let responseString = String(data: data, encoding: .utf8) {
        print("Response: \(responseString)")
    }
}

task.resume()

3. 发送 POST 请求

3.1 修改请求方法和添加请求体

要发送 POST 请求,我们需要修改请求方法,并添加请求体。请求体通常是一个 JSON 格式的字符串。

guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
    fatalError("Invalid URL")
}

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")

let json: [String: Any] = ["title": "foo", "body": "bar", "userId": 1]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
request.httpBody = jsonData

3.2 创建并启动数据任务

与 GET 请求类似,我们创建并启动数据任务。

let task = session.dataTask(with: request) { data, response, error in
    if let error = error {
        print("Error: \(error.localizedDescription)")
        return
    }
    
    guard let data = data else {
        print("No data received")
        return
    }
    
    if let responseString = String(data: data, encoding: .utf8) {
        print("Response: \(responseString)")
    }
}

task.resume()

3.3 完整代码示例

import Foundation

let session = URLSession.shared

guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
    fatalError("Invalid URL")
}

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")

let json: [String: Any] = ["title": "foo", "body": "bar", "userId": 1]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
request.httpBody = jsonData

let task = session.dataTask(with: request) { data, response, error in
    if let error = error {
        print("Error: \(error.localizedDescription)")
        return
    }
    
    guard let data = data else {
        print("No data received")
        return
    }
    
    if let responseString = String(data: data, encoding: .utf8) {
        print("Response: \(responseString)")
    }
}

task.resume()

4. 处理响应数据

4.1 解析 JSON 数据

通常,服务器返回的数据是 JSON 格式的。我们可以使用 JSONSerialization 或 Codable 协议来解析 JSON 数据。

struct Post: Codable {
    let id: Int
    let title: String
    let body: String
    let userId: Int
}

let task = session.dataTask(with: request) { data, response, error in
    if let error = error {
        print("Error: \(error.localizedDescription)")
        return
    }
    
    guard let data = data else {
        print("No data received")
        return
    }
    
    do {
        let post = try JSONDecoder().decode(Post.self, from: data)
        print("Post: \(post)")
    } catch {
        print("Error decoding JSON: \(error.localizedDescription)")
    }
}

task.resume()

4.2 处理 HTTP 状态码

我们还可以检查 HTTP 响应的状态码,以确保请求成功。

let task = session.dataTask(with: request) { data, response, error in
    if let error = error {
        print("Error: \(error.localizedDescription)")
        return
    }
    
    guard let httpResponse = response as? HTTPURLResponse,
          (200...299).contains(httpResponse.statusCode) else {
        print("Invalid response")
        return
    }
    
    guard let data = data else {
        print("No data received")
        return
    }
    
    do {
        let post = try JSONDecoder().decode(Post.self, from: data)
        print("Post: \(post)")
    } catch {
        print("Error decoding JSON: \(error.localizedDescription)")
    }
}

task.resume()

5. 实践练习

5.1 练习 1: 获取用户列表

编写一个程序,从 https://jsonplaceholder.typicode.com/users 获取用户列表,并打印每个用户的姓名和电子邮件。

5.2 练习 2: 创建新用户

编写一个程序,向 https://jsonplaceholder.typicode.com/users 发送一个 POST 请求,创建一个新用户,并打印服务器的响应。

6. 总结

URLSession 是 iOS 开发中处理网络请求的重要工具。通过本教程,你学会了如何使用 URLSession 发送 GET 和 POST 请求,处理响应数据,以及处理错误。希望这些知识能帮助你在实际项目中更好地处理网络请求。

7. 进一步学习

  • 上传和下载任务: 学习如何使用 URLSession 上传和下载文件。
  • 自定义会话配置: 了解如何使用 URLSessionConfiguration 自定义会话的属性。
  • 处理身份验证: 学习如何处理需要身份验证的网络请求。

通过不断练习和探索,你将能够更熟练地使用 URLSession,并在实际项目中应用这些知识。